function SpCheckList(clientName, divMenuId, valueId, textId, enable, visible, valueSpliter, textSpliter, panelId, displayEffect, timeEffect, stepEffect, menuItemId, allCheck) {
	var _selectedMenuStyle = "chlMenuItemSelect";
	var _unSelectedMenuStype = "chlMenuItem";
	var _focusMenuStyle = "chlMenuItemActive";
	var _inputPanelEnable = "chlInputPanel";
	var _inputPanelDisable = "chlInputPanelDisable";
	var _hashParameter = Library.WebControl.Hashtable.CreateHashtable();
	var _effectControl = null;
	var _instance = this;
	var _util = Library.WebControl.Util;
	var _valueId = valueId;
	var _textId = textId;
	var _divMenuId = divMenuId;
	var _enable = enable;
	var _visible = visible;
	var _valueSpliter = valueSpliter;
	var _textSpliter = textSpliter;	
	var _checkChanged;
	var _panelId = panelId;
	var _displayEffect = displayEffect;
	var _timeEffect = timeEffect;
	var _stepEffect = stepEffect;
	var _currentScrollTop = 0;
	var _currentScrollLeft = 0;
	var _menuItemId = menuItemId;
	var _allCheck = allCheck;
	var _isInputCheck = false;
	var _selectIndexChanged = null;
	var _shown = null;	
	_globalHashObject.Add(clientName, _instance);
	window[clientName] = _instance;	
	function getTextControl() {
		return _util.GetObjectById(_textId);
	};

	function getValueControl() {
		return _util.GetObjectById(_valueId);
	};

	function getDivMenu() {
		return _util.GetObjectById(_divMenuId);
	};

	function getValueFromMenuItem(mi) {
		var t = mi.getAttribute("_spexcomboboxkey_");
		if (t == null)
			t = "";
		return t;
	};

	function normalStyle(mi) {
		if (isSelected(mi)) {
			_util.SetClass(mi, _selectedMenuStyle);
		} else {
			_util.SetClass(mi, _unSelectedMenuStype);
		}
	};
	function focusStype(mi) {
		_util.SetClass(mi, _focusMenuStyle);
	};
	function getTextFromMenuItem(mi) {
		var t = mi.getAttribute("_spexcomboboxvalue_");
		if (t == null)
			t = "";
		return t;
	};
	function getMenuItem() {
		return _util.GetObjectById(_menuItemId);
	};


	function parseText(t) {
		if ( typeof (t) == "string") {
			var newText = "";
			var newValue = "";
			var ts = t.split(_textSpliter);
			var m = _util.GetObjectById(_menuItemId);
			for (var i = 0; i < m.childNodes.length; i++) {
				var node = m.childNodes[i];
				if (node.tagName.toLowerCase() == "div") {
					var text = getTextFromMenuItem(node);
					var match = false;
					for (var j = 0; j < ts.length; j++) {
						if (ts[j] == text) {
							var v = getValueFromMenuItem(node);

							match = true;
							setState(node, true);
							if (newValue == "") {
								newValue = v;
							} else {
								newValue += _valueSpliter + v;
							}

							if (newText == "") {
								newText = text;
							} else {
								newText += _textSpliter + text;
							}

							break;
						}
					}

					if (!match) {
						setState(node, false);
					}
				}
			}

			getValueControl().value = newValue;
			getTextControl().value = newText;
		}
	};
	function parseArrValue(vs) {
		var newText = "";
		var newValue = "";

		var m = _util.GetObjectById(_menuItemId);
		for (var i = 0; i < m.childNodes.length; i++) {
			var node = m.childNodes[i];
			if (node.tagName.toLowerCase() == "div") {
				var v = getValueFromMenuItem(node);
				var match = false;
				for (var j = 0; j < vs.length; j++) {
					if (vs[j] == v) {
						setState(node, true);
						match = true;
						var t = getTextFromMenuItem(node);
						if (newText == "") {
							newText = t;
						} else {
							newText += _textSpliter + t;
						}
						if (newValue == "") {
							newValue = v;
						} else {
							newValue += _valueSpliter + v;
						}
						break;
					}
				}

				if (!match) {
					setState(node, false);
				}
			}
		}

		getTextControl().value = newText;
		getValueControl().value = newValue;
	};
	function parseValue(v) {
		if ( v instanceof Array) {
			parseArrValue(v);
		} else if ( typeof (v) == "string") {
			var vs = v.split(_valueSpliter);
			parseArrValue(vs);
		}
	};
	function isMenuVisible() {
		return getDivMenu().style.visibility != "hidden";
	};
	function isSelected(mi) {
		return getCheckBoxFromMenuItem(mi).checked;
	};
	function getCheckBoxFromMenuItem(mi) {
		var ips = mi.getElementsByTagName("input");
		return ips[0];
	};
	function changeMenuItemState(mi) {
		// if check change to uncheck
		//
		var c = getCheckBoxFromMenuItem(mi);
		c.checked = !c.checked;
	};

	function changeFocusState() {
		var dm = getDivMenu();
		if (dm.childNodes.length == 0)
			return;
		if (_focusItemIndex < 0 || _focusItemIndex >= dm.childNodes.length)
			return;
		changeMenuItemState(dm.childNodes[_focusItemIndex]);
	};

	this.SetEnable = function(enable) {
		_enable = enable;
		var clzz = enable ? _inputPanelEnable : _inputPanelDisable;
		_util.SetClass(_util.GetObjectById(_panelId), clzz);
	};
	this.Show = function() {
		if (!_enable)
			return;
		if (isMenuVisible())
			return;
		_checkChanged = false;
		var divMenu = getDivMenu();
		if (divMenu.childNodes.length == 0)
			return;
		divMenu.style.zIndex = _util.GetMaxZindex() + 1;
		divMenu.style.display = "block";

		if (_effectControl == null) {
			_effectControl = Library.WebControl.Effect.Create({
				Object : divMenu,
				Type : _displayEffect,
				Time : _timeEffect,
				Step : _stepEffect,
				ObjHeight : divMenu.clientHeight,
				ObjWidth : divMenu.clientWidth,
				Vision : 'V',
				ShowComplete : function(s, e) {
					divMenu.style.display = "block";
					divMenu.style.overflow = "auto";
					divMenu.scrollTop = _currentScrollTop;
					divMenu.scrollLeft = _currentScrollLeft;
					var divSize = _util.GetSize(divMenu);
					var panelSize = _util.GetSize(_panelId);
					if (divSize.W < panelSize.W) {
						divMenu.style.width = panelSize.W + "px";
					}
					if (_shown != null) _shown(_instance, {});					
				},
				HideComplete : function(s, e) {
					divMenu.style.display = "none";
					//divMenu.style.top = "-1000px";
					//divMenu.style.left = "-1000px";
					divMenu.style.zIndex = 0;
				}
			});
		}
		_effectControl.Show();

	};
	this.GetText = function() {
		return getTextControl().value;
	};
	this.SetText = function(text) {
		parseText(text);
	};
	this.GetValue = function() {
		return getValueControl().value;
	};
	this.SetValue = function(v) {
		parseValue(v);
	};
	this.Hide = function() {
		var divMenu = getDivMenu();
		_currentScrollTop = divMenu.scrollTop;
		_currentScrollLeft = divMenu.scrollLeft;

		if (_checkChanged) {
			var texts = "";
			var values = "";
			var div = getMenuItem();
			for (var i = 0; i < div.childNodes.length; i++) {
				var mi = div.childNodes[i];
				if (isSelected(mi)) {
					var t = getTextFromMenuItem(mi);
					var v = getValueFromMenuItem(mi);
					if (texts == "")
						texts = t;
					else
						texts += _textSpliter + t;
					if (values == "")
						values = v;
					else
						values += _valueSpliter + v;
				}
			}
			var tctr = getTextControl();
			var vctr = getValueControl();
			vctr.value = values;
			tctr.value = texts;
			if (_selectIndexChanged != null) _selectIndexChanged(_instance, {});			
		}
		if (_effectControl) {
			_effectControl.Hide();
		}
	};
	 function changeAll (c) {
		if (_allCheck == 2)
			return;
		
		
		if (c.checked) {
			var m = _util.GetObjectById(_menuItemId);
			for (var i = 0; i < m.childNodes.length; i++) {
				var node = m.childNodes[i];
				if (node.tagName.toLowerCase() == "div") {
					setState(node, false);
				}
			}
			_allCheck = 1;
			getValueControl().value = c.getAttribute("_value_");
			getTextControl().value = c.getAttribute("_text_");
		
		} else {
			_allCheck = 0;
			getValueControl().value = "";
			getTextControl().value = "";
		}
		_checkChanged = false;
	};
	function setState(mi, value) {
		var c = mi.getElementsByTagName('input')[0];
		if (c.checked == value)
			return false;
		c.checked = !c.checked;
		if (!c.checked) {
			normalStyle(mi);
		} else {
			focusStype(mi);
		}
		_checkChanged = true;
		return c.checked;
	};
	
	 function changeState(mi) {
		if (_allCheck == 1)
			return false;
		if (mi.tagName.toLowerCase() == "input") {
			_isInputCheck = true;
			var c = mi;
			if (!c.checked) {
				normalStyle(c.parentNode.parentNode);
			} else {
				focusStype(c.parentNode.parentNode);
			}
		_checkChanged = true;
		
			return c.checked;
		} else {	
			if (_isInputCheck) {
				_isInputCheck = false;
				return false;
			}
			return setState(mi);
		}
	};

	function commonSendCallback(parameter, callbackFunction) {
		_util.ShowLoadingPanel({Parrent: _panelId, LoadingId: _panelId + '_LDP'});
		var ajaxRequest = Library.WebControl.Ajax.CreateRequest();
		ajaxRequest.SetData("__SPCHECKLISTRQP_=T&__SPCHECKLISTRQSID_=" + _divMenuId + "&__SPCHECKLISTRQD_=" + encodeURIComponent(parameter) + "&" + _hashParameter.ToQuery());
		_hashParameter.Clear();
		ajaxRequest.SendCallback({
			P : parameter,

			F : callbackFunction
		}, callbackComplete);
	};

	this.SendCallback = function(parameter, callbackFunction) {		
		commonSendCallback(parameter, callbackFunction);
	};
	function callbackComplete(sender, args) {
		var callbackEventArgs = _util.ParseAjaxResponse(args.ResponseText);
		callbackEventArgs.Parameter = sender.P;
		var responseResult = callbackEventArgs;
		if (!callbackEventArgs.IsValid) {
			alert(responseResult.Result);
		} else {
			var divMenu = getMenuItem();
			var rsArr = _util.ParseArrResponse(responseResult.Data);
			getValueControl().value = rsArr[0];
			getTextControl().value = rsArr[1];			
			_util.EvalScriptAndHtml(rsArr[2], divMenu);
		}
		_util.HideLoadingPanel(_panelId + '_LDP');
		if (sender.F && typeof (sender.F) == "function") {
			sender.F(_instance, callbackEventArgs);
		}
		
	};
	this.Call=function(t, p) {
		switch(t) {
			case 1:// key press;
				return _enable;
			case 2:
				changeAll(p);
				break;	
			case 3:
				return changeState(p);	
		}
	};
	this.AddHandler = function(t, f) {
		switch(t) {
			case 1:
				_selectIndexChanged  = f;
				break;
			case 2:
				_shown = f;
				break;	
		}
	};
	
	this.AddParameter = function(a, b) {
		_hashParameter.Add(a, b);
	};
			
	this.ValueToString = function(spliter) {
		if (!spliter) {
			return getValueControl().value;
		}

		return getValueControl().value.split(_valueSpliter).join(spliter);

	};
};
